/*
 * Scheduler.cpp
 *
 *  Created on: Jan 13, 2010
 *      Author: artur
 */

#include <Console.h>

#include <sys/sched/Scheduler.h>
#include <hw/Platform.h>
#include <cpu/Cpu.h>

#include <kiddie/kiddie.h>

extern ::kernel::Console cout;
extern ::kernel::Platform hwplatform;
extern ::util::list<kernel::sys::sched::task::Task *> running;
extern ::util::list<kernel::sys::sched::task::Task *> finished;

extern ::kernel::sys::sched::task::Task *current;

namespace kernel
{
  namespace sys
  {
    namespace sched
    {

      Scheduler::Scheduler()
      {
        // TODO Auto-generated constructor stub
        ::cout << "[ Scheduler ] Constructor\n";
      }

      Scheduler::~Scheduler()
      {
        ::cout << "[ Scheduler ] Destructor\n";
      }

      Scheduler &
      Scheduler::operator -=(task::Task *tsk)
      {
        running.remove(tsk);
        ::cout << "[ Scheduler ] Removed task entry=" << (int) tsk->entry
            << "\n";
        ::cout << "[ Scheduler ] Size=" << running.size << "\n";
        return *this;
      }

      Scheduler &
      Scheduler::operator <<(task::Task *tsk)
      {
        *this += (tsk);
        return *this;
      }

      Scheduler &
      Scheduler::operator +=(task::Task *tsk)
      {
        ::running.add(tsk);
        ::cout << "[ Scheduler ] Added new task, Size = " << (int) running.size
            << "\n";
        ::cout << kernel::Console::HEX << "[ Scheduler ] Tsk: entry(0x"
            << (int) tsk->entry << "), PL(0x" << (int) tsk->pl
            << "), CTX.U_STACK(0x" << (int) tsk->tsk_context.u_stack_top
            << ")\n";
        return *this;
      }

      Scheduler &
      Scheduler::operator <<(::kernel::cmd::CMD cmd)
      {
        switch (cmd)
          {
        case ::kernel::cmd::INIT:
          /* state is INIT */
          SchedState = kernel::cmd::INIT;
          break;

        case ::kernel::cmd::PAUSE:
          SchedState = kernel::cmd::PAUSE;
          break;

        case ::kernel::cmd::RESUME:
          SchedState = kernel::cmd::START;
          break;

        case ::kernel::cmd::STOP:
          SchedState = kernel::cmd::STOP;
          break;

        case ::kernel::cmd::START:
          SchedState = kernel::cmd::START;
          break;

        case ::kernel::cmd::CONTINUE:
          if (this->SchedState == kernel::cmd::START)
            {
              /* TODO */
              task::Task *prev = ::current;
              ::current = running.next();
              if (prev == ::current)
                return *this;
              ::hwplatform.bootCpu._swap(prev, current);
              // hwplatform.bootCpu << SWAPCMD << current << tsk;
            }
          break;

          }
        return *this;
      }

      void
      Scheduler::onEvent(::kernel::irq::Event *evt)
      {
        //	::cout <<  "[ Sched ] onEvent()\n";
        *this << ::kernel::cmd::CONTINUE;
      }

    }
  }
}
